
/*
 * @项目名称: 模板开发
 * @FilePath: /meek/src/renderer/render/cuberender.js
 * @Author: 
 * @Date: 2017-03-23T11:12:12+08:00
 * @LastEditors: 447508585@qq.com
 * @LastEditTime: 2023-03-16 15:20:30
 * Copyright (c) 2018-2022 
 */

/**
 * Created by zhangyong on 2017/3/20.
 */
import Geometry from '../../geometry/geometry'
import GeometryRender from '../render/geomertyrender'
import LineStyle from '../../style/linestyle'
import {
  Transform
} from '../../data/matrix/transform'
import {
  colorToString
} from '../../utils/helpers'
import {drawPoint} from './drawPoint';
import {
  CubeUtil
} from "../../geometry/support/cubeutil";
export default class PolygonRender extends GeometryRender {

  constructor(context) {
    super(context)
  }

  /**
   * Render a polygon
   * @param feature
   * @param transform
   * @returns {boolean}
   */
  render(feature, renderStyle, transform) {

    if (!feature) {
      return
    }
    const ctx = this.context
    const styleArray = renderStyle
    const geometry = feature.geometry

    const transform2D = Transform.transform2D
    let geometryCoordinages = geometry.getCoordinates()
    if (geometry.geometryType === Geometry.EXTENT) {
      geometryCoordinages = [geometryCoordinages]
    }

    if (!geometryCoordinages) {
      return false
    }

    if (geometryCoordinages.length === 0) {
      return false
    }
    // TODO find a way to cache the rendered data
    let coordinates = []
    let renderCoords = []

    if (this._pixelCoordinates &&
      this.equalsTransform(transform, this.renderedTransform)) {
      renderCoords = this._pixelCoordinates
    } else {
      if (geometry.geometryType === Geometry.MULTI_POLYGON || geometry.geometryType === Geometry.CUBE) {
        let polygonCoords = []
        // 遍历各个多边形
        geometryCoordinages.forEach(polygon => {
          polygon.forEach(rings => {
            rings.forEach(points => {
              let coordinate = transform2D(
                points, 0, points.length, 2,
                transform)

              coordinate[0] = (coordinate[0] + 0.5) | 0
              coordinate[1] = (coordinate[1] + 0.5) | 0

              coordinates.push(coordinate)
            })

            polygonCoords.push(coordinates)
            coordinates = []
          })

          renderCoords.push(polygonCoords)
          polygonCoords = []
        })
        this.renderMutilPolygon(ctx, styleArray, renderCoords, feature)

      } else {
        // 遍历多边形各个环
        geometryCoordinages.forEach(rings => {
          rings.forEach(points => {
            let coordinate = transform2D(
              points, 0, points.length, 2,
              transform)
            coordinate[0] = (coordinate[0] + 0.5) | 0
            coordinate[1] = (coordinate[1] + 0.5) | 0

            coordinates.push(coordinate)
          })

          renderCoords.push(coordinates)
          coordinates = []
        })
        this.renderPolygon(ctx, styleArray, renderCoords, geometry)
        drawPoint(ctx, renderCoords, feature, styleArray)
        //this.renderPolygon(ctx, styleArray, renderCoords)
      }

      //this.renderPolygon(ctx, styleArray, renderCoords, geometry)
    }

    this._pixelCoordinates = renderCoords
    Transform.setFromArray(this.renderedTransform, transform)

    return true
  }

  /**
   *
   * @param ctx
   * @param styleArray
   * @param renderCoords
   */
  renderMutilPolygon(ctx, styleArray, renderCoords, feature) {
    let geometry = feature.geometry;
    renderCoords.forEach((polygon, index) => {
      this.renderPolygon(ctx, styleArray, polygon, index, geometry,feature, renderCoords)
    })
  }

  /**
   *
   * @param ctx
   * @param styleArray
   * @param renderCoords
   */
  renderPolygon(ctx, styleArray, renderCoords, index, geometry, feature, cubeCoords) {
    const len = styleArray.length
    if (feature) {
      drawPoint(ctx, renderCoords, feature, styleArray)
    }

    for (let i = 0; i < len; i++) {
      let styleObj = styleArray[i]

      let renderOptions = {
        coordinates: renderCoords,
        fillStyle: colorToString(styleObj.color, styleObj.alpha),
        borderStyle: styleObj.borderStyle,
        cubeCoords: cubeCoords // 全部的坐标
      }
      this.drawStylePolygon(ctx, renderOptions, index, geometry)
    }
  }

  /**
   * 绘制多边形，需要注意多边形各个环的绘制
   * @param ctx
   * @param renderOpt
   */
  drawStylePolygon(ctx, renderOpt, index, geometry) {
    const currentFace = geometry && geometry.currentFace
    ctx.save()

    const cubeCoords = renderOpt.cubeCoords;

    if (renderOpt.fillStyle) {
      ctx.fillStyle = renderOpt.fillStyle
    }
    const dashdot = [15, 15, 5, 15];
    const dash = [1,2];

    const borderStyle = renderOpt.borderStyle
    if (borderStyle) {
      ctx.strokeStyle = colorToString(borderStyle.color, borderStyle.alpha)
      ctx.lineWidth = borderStyle.width

      if (borderStyle.style === LineStyle.DASH) {
        ctx.setLineDash(dash)
      }
    }

    const coords = renderOpt.coordinates

    ctx.save()

    coords.forEach((coordinates, index) => {
      //return;
      if (index === 0) {
        ctx.beginPath()
      }
      ctx.moveTo(coordinates[0][0], coordinates[0][1])
      for (let k = 1, kk = coordinates.length; k < kk; k++) {
        let cd = coordinates[k]
        ctx.lineTo(cd[0], cd[1])
      }

      ctx.closePath()
    })
    ctx.fill()
    //ctx.stroke()
    if (index === 0) {
      if (borderStyle.style === LineStyle.DASHDOT) {
        ctx.setLineDash(dashdot)
      }
      ctx.stroke()
    }


    if (currentFace!==null && index === currentFace) {
      drawRect(ctx, coords[0], 0.1);
    }

    //if (index === 0 && mapController.hlFirstFace) {
    // if (index === 0) {
    //   drawRect(ctx, coords[0], 0.3);
    // }

    if (index === 1 || index === 4 || index === 3) {
      const geoCoords = geometry.getCoordinates();
      const currentFace = geoCoords[index][0]

      let evaluatedFaces = []
      let hangeFaces = []

      if (index === 1 || index === 4) {
        hangeFaces.push(geoCoords[0][0], geoCoords[3][0])
        evaluatedFaces.push(geoCoords[0][0])
        if (geoCoords[0][0][0][1] > geoCoords[3][0][0][1]) {
          evaluatedFaces.push(geoCoords[2][0])
        } else {
          evaluatedFaces.push(geoCoords[5][0])
        }
      }

      if (index === 3) {
        evaluatedFaces.push(geoCoords[0][0], geoCoords[2][0], geoCoords[1][0], geoCoords[4][0], geoCoords[5][0])
      }

      const coord = coords[0];
      coord.forEach((p, i) => {
        let nextP = coord[i + 1]
        if (!nextP) {
          nextP = coord[0]
        }

        let p1 = currentFace[i]
        let p2 = currentFace[i + 1]
        if (!p2) {
          p2 = currentFace[0]
        }

        const line = [p1, p2];

        const isEdge = hangeFaces.some((face) => {
          return CubeUtil.isLineTheEdgeOfTheFace(line, face);
        })

        if (isEdge) {
          return;
        }

        // 目前只有前后梯形后面的上下边会存在半实线半虚的情况
        // 需要判断是否有相交点，并计算相交点
        // 1 -> 2
        // 3 -> 0
        let sep = false;
        if (geometry.cubeMode === 3 && index === 3) {
          if (i === 1 || i === 3) {
            const lines = CubeUtil.getIntersectedLinesOfLineWithFace([p, nextP], cubeCoords[0][0], i);
            if (lines) {
              sep = true;
              lines.forEach(line => {
                const coord = line.coord;
                drawLine(ctx, coord[0], coord[1], getLineStyle(line.visible, borderStyle))
              })
            }
          }
        }

        if (!sep) {
          const isIntersected = evaluatedFaces.some((face, index) => {
            return CubeUtil.isEdgeIntersectWidthFace(line, face);
          })

          drawLine(ctx, p, nextP, getLineStyle(!isIntersected, borderStyle));
        }

        /*

        if (isIntersected) {
          drawLine(ctx, p, nextP, [5, 10])
        } else {
          if (borderStyle.style === LineStyle.DASHDOT) {
            drawLine(ctx, p, nextP, dashdot)
          } else if (borderStyle.style === LineStyle.DASH) {
            drawLine(ctx, p, nextP, dash)
          } else {
            drawLine(ctx, p, nextP)
          }
        }
        */
      })
    }

    if (geometry && index === geometry.direction) {
      ctx.restore()
      ctx.save()
      hlFace(ctx, coords[0]);
    }
    ctx.restore()
    ctx.restore()
  }
}

function getLineStyle(visible, borderStyle) {
  const dashdot = [15, 15, 5, 15];
  const dash = [1,2];

  if (!visible) {
    return [5, 10];
  } else if (borderStyle) {
    if (borderStyle.style === LineStyle.DASHDOT) {
      return dashdot;
    } else if (borderStyle.style === LineStyle.DASH) {
      return dash;
    }
  }
}

function hlFace(ctx, coords) {
  drawLine(ctx, coords[0], coords[2]);
  drawLine(ctx, coords[1], coords[3]);
}

function drawLine(ctx, start, end, dash = []) {
  ctx.save()
  ctx.setLineDash(dash)
  ctx.beginPath();
  ctx.moveTo(start[0], start[1]);
  ctx.lineTo(end[0], end[1]);
  ctx.closePath();
  ctx.stroke();
  ctx.restore()
}

function drawRect (ctx, coordinates, opacity) {
  ctx.beginPath()
  let fillStyle = ctx.fillStyle;
  let alpha = fillStyle.substring(fillStyle.lastIndexOf(',') + 1, fillStyle.length - 1);
  fillStyle = fillStyle.replace(alpha+')', (Number(alpha.trim()) + opacity).toString()+')');
  // fillStyle = 'red';
  ctx.fillStyle = fillStyle;
  ctx.moveTo(coordinates[0][0], coordinates[0][1])
  for (let k = 1, kk = coordinates.length; k < kk; k++) {
    let cd = coordinates[k]
    ctx.lineTo(cd[0], cd[1])
  }
  ctx.lineTo(coordinates[0][0], coordinates[0][1])
  ctx.closePath()
  ctx.fill()
}
